﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;
using Phoenix.Installer;
using System.Diagnostics;

namespace ServiceInstaller {
    class Program {
        static string[] services = new string[] { };
        static Regex serviceRegex = new Regex(@"services=(?<Services>.*)",
            RegexOptions.Compiled | RegexOptions.IgnoreCase);
        static IServiceInstaller _serviceInstaller;
        const string INSTALL_UTIL_FILENAME = @"C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe";

        static void Main(string[] args) {
            System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);
            var argsValue = String.Join(" ", args);
            var assemblyFile = args[0];
            var isInstall = args.Length > 0 && args[1] == "install";
            var serviceMatch = serviceRegex.Match(argsValue);
            var asm = Assembly.LoadFrom(assemblyFile);
            var serviceType = typeof(IServiceInstaller);
            var type = asm.GetTypes()
                .Where(x => serviceType.IsAssignableFrom(x)).FirstOrDefault();
            if (type == null) return;
            _serviceInstaller = Activator.CreateInstance(type) as IServiceInstaller;
            if (serviceMatch.Success)
                services = serviceMatch.Groups["Services"].Value.Split(',');
            if (isInstall) Install();
            else UnInstall();
        }

        static IEnumerable<ServiceInstallerInfo> Services {
            get {
                var serviceInfos = _serviceInstaller.Services;
                serviceInfos = services.Length > 0 ?
                serviceInfos.Where(serviceInfo => services.Any(service => serviceInfo.Name == service))
                : serviceInfos;
                return serviceInfos;       
            }
        }

        private static void ExecuteFile(string filename, string arguments) {
            ProcessStartInfo info = new ProcessStartInfo(filename);
            info.Arguments = arguments;
            info.UseShellExecute = false;
            info.CreateNoWindow = true;
            info.ErrorDialog = false;
            info.WindowStyle = ProcessWindowStyle.Hidden;
            var process = Process.Start(info);
            process.WaitForExit();
        }

        static void UnInstall() {
            Services.ToList().ForEach(service => ExecuteFile(INSTALL_UTIL_FILENAME,
                    String.Format("/u /name=\"{0}\" \"{1}\"", service.Name, service.ExeFileName)));
        }

        static void Install() {
            Services.ToList().ForEach(service => ExecuteFile(INSTALL_UTIL_FILENAME, 
                    String.Format("/name=\"{0}\" /username=\"localsystem\" /password=\"\" /displayname=\"{0}\" /dependon=\"{2}\" /description=\"{1}\" /id=\"{0}\" \"{3}\"",
                        service.Name, service.Description,
                        service.DependOn, service.ExeFileName)));
        }
    }
}
